home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / bc_pas_1.zip / PCMIOA.ASM < prev    next >
Assembly Source File  |  1992-12-08  |  18KB  |  775 lines

  1. ;$Author:   DCODY  $
  2. ;$Date:   08 Dec 1992 17:15:00  $
  3. ;$Header:   X:/sccs/pcm/pcmioa.asv   1.7   08 Dec 1992 17:15:00   DCODY  $
  4. ;$Log:   X:/sccs/pcm/pcmioa.asv  $
  5. ;  
  6. ;     Rev 1.7   08 Dec 1992 17:15:00   DCODY
  7. ;  moved externADDR macro for Borland link.
  8. ;  
  9. ;     Rev 1.6   20 Oct 1992 10:09:08   DCODY
  10. ;  adjusted tiny model .data declaration and segment use. removed binary.inc
  11. ;  as an include file.
  12. ;  
  13. ;     Rev 1.5   06 Oct 1992 16:00:44   DCODY
  14. ;  added direct dos read/write file routines.
  15. ;  
  16. ;     Rev 1.4   23 Sep 1992 10:57:04   DCODY
  17. ;  more work on playthisblock, continuethisblock...
  18. ;  
  19. ;     Rev 1.3   26 Aug 1992 10:58:26   DCODY
  20. ;  added Playthisblock and RecordthisBlock support routines
  21. ;  
  22. ;     Rev 1.2   12 Aug 1992 17:10:56   DCODY
  23. ;  major change to eliminate the foreground buffers and background
  24. ;  processing responsibilities.
  25. ;  
  26. ;     Rev 1.1   23 Jun 1992 17:11:34   DCODY
  27. ;  PAS2 update
  28. ;  
  29. ;     Rev 1.0   15 Jun 1992 09:44:36   BCRANE
  30. ;  Initial revision.
  31. ;$Logfile:   X:/sccs/pcm/pcmioa.asv  $
  32. ;$Modtimes$
  33. ;$Revision:   1.7  $
  34. ;$Workfile:   pcmioa.asm  $ 
  35.  
  36.  
  37.     page    64,131
  38.     Title    PCMIOA    --  Background Task for PCM I/O
  39.  
  40. ;   /*\
  41. ;---|*|------------====< PCMIOA.ASM >====------------
  42. ;---|*|
  43. ;---|*| Copyright (c) 1991, Media Vision, Inc. All rights reserved
  44. ;---|*|
  45. ;   \*/
  46.  
  47.         .xlist
  48.     include model.inc
  49.     include masm.inc
  50.         include common.inc
  51.     .list
  52.  
  53. PCMCODEVERSION    equ    0003h        ; version 00.03
  54.  
  55. ;
  56. ;-----------------------================================-----------------------
  57. ;-----------------------====< Code/Data Generation >====-----------------------
  58. ;-----------------------================================-----------------------
  59. ;
  60.  
  61. BLOCKOUT    = 0        ; builds block output code only
  62. BLOCKIN     = 0        ; builds block input code only
  63. COMMDATA    = 0        ; builds both common code and data
  64.  
  65. ifdef  BUILDBO
  66.   BLOCKOUT    = 1
  67. endif
  68.  
  69. ifdef  BUILDBI
  70.   BLOCKIN    = 1
  71. endif
  72.  
  73. ifdef  BUILDCO
  74.   COMMDATA    = 1
  75. endif
  76.  
  77.     externADDR    InitPCM         ; initialize the PCM low level code
  78.     externADDR    StopPCM         ; Kill the PCM hardware
  79.     externADDR    PCMPlay         ; start the PCM output
  80.     externADDR    PCMRecord        ; start the PCM input
  81.     externADDR    UserFunc        ; sets up the call-back routine
  82.  
  83. if (BLOCKOUT or BLOCKIN)
  84.     externADDR    _resetdmaptrs        ; reset the criticals
  85. endif
  86.  
  87. ;
  88. ;---------------------------========================---------------------------
  89. ;---------------------------====< DATA SECTION >====---------------------------
  90. ;---------------------------========================---------------------------
  91. ;
  92. if MODELSIZE eq 0
  93.     .code
  94. else
  95.     .data
  96. endif
  97.  
  98. ;
  99. ; Code Model Dependencies
  100. ;
  101. if @datasize
  102.   cptr    equ    <dword>         ; C pointer is FAR
  103. else
  104.   cptr    equ    <word>            ; C pointer is NEAR
  105. endif
  106.  
  107. NODIRECTION    equ    0
  108. DMAINPUT    equ    1
  109. DMAOUTPUT    equ    2
  110.  
  111. PCMFILEINPUT    equ    DMAINPUT
  112. PCMFILEOUTPUT    equ    DMAOUTPUT
  113. PCMBLOCKINPUT    equ    DMAINPUT+80h
  114. PCMBLOCKOUTPUT    equ    DMAOUTPUT+80h
  115.  
  116. ;
  117. ; Structure Definitions
  118. ;
  119. buffptr struc
  120.  
  121.  BPstatus       dw      0               ; 0=empty, 1=full
  122.  BPcount    dw    0        ; # of bytes in the buffer
  123.  BPsize     dw    0        ; total size of allocated buff
  124.  BPbuffer    dd    0        ; pointer to buffer data
  125.  
  126.   if @datasize
  127.    BPnextptr    dd    0        ; pointer to buffer data
  128.   else
  129.    BPnextptr    dw    0        ; pointer to buffer data
  130.   endif
  131.  
  132. buffptr ends
  133.  
  134. ;
  135. ;--------------====< code generation dependent declarations >====------------
  136. ;
  137.  
  138. if    COMMDATA
  139.  
  140. ;
  141. ; Local data declarations
  142. ;
  143.     public    CountdownBuffers
  144. CountdownBuffers    db    00    ; countdown value
  145.     public    NextDMAPtr
  146. NextDMAPtr        dd    00    ; our pointer to the DMA's buffer
  147.     public    DMAUnitSize
  148. DMAUnitSize        dw    00    ; size of DMA buffer divisions
  149.  
  150.     public    __callersroutine
  151.   if @codesize
  152. __callersroutine        dd      00
  153.   else
  154. __callersroutine    dw    00
  155.   endif
  156.  
  157. else
  158.     extrn    __callersroutine :word
  159.     extrn    __NextPtr     :dword ; pointer to circular buffer list
  160. ;
  161. ; Local data declarations
  162. ;
  163.     extrn    CountdownBuffers :byte    ; countdown value
  164.     extrn    NextDMAPtr     :dword ; our pointer to the DMA's buffer
  165.     extrn    DMAUnitSize     :word    ; size of DMA buffer divisions
  166.  
  167. endif
  168.     externPTR    HeadOfBuffers        ; pointer to buffer linked list
  169.     extrn    BufferDataCount  :word    ; # of full buffers (0=done)
  170.     extrn    DMARunning     :word    ; DMA status (0=off,1=running)
  171.     extrn    StartOfDMABuffer :dword ; always a far * to start of DMA buffer
  172.     extrn __pcmdatasize     :byte    ; default to 8 bit pcm
  173.     extrn    MaxBuffCount     :word    ; count of DMA blocks
  174.     extrn    ProcessedBlockCount:word; # of full buffers (0=done)
  175.     extrn    __synccallback     :dword ; callback to application at int
  176.     extrn    __fptrpos     :dword ; file position byte count pointer
  177.  
  178. ;
  179. ;---------------------------========================---------------------------
  180. ;---------------------------====< CODE SECTION >====---------------------------
  181. ;---------------------------========================---------------------------
  182. ;
  183.         .code
  184.  
  185. if COMMDATA
  186.  
  187. ;   /*\
  188. ;---|*|------------====< BackgroundInit( int, int ) >====------------
  189. ;---|*|
  190. ;---|*| Initialize our internal variables, etc...
  191. ;---|*|
  192. ;---|*| Entry Conditions:
  193. ;---|*|     wParm1 - Size of DMA buffer
  194. ;---|*|     wParm2 - # of DMA buffer divisions
  195. ;---|*|
  196. ;---|*| Exit Conditions:
  197. ;---|*|     No return value
  198. ;---|*|
  199. ;---|*| Functionality:
  200. ;---|*|
  201. ;---|*|     Clear interrupt mechanisms.
  202. ;---|*|     Disable DMA channel.
  203. ;---|*|     Set DMARunning to 0;
  204. ;---|*|
  205. ;   \*/
  206.  
  207.         public  BackgroundInit
  208. BackgroundInit    proc
  209.     push    bp
  210.     mov    bp,sp
  211.     push    es
  212. ;
  213. ; get the # of buffers in the linked list
  214. ;
  215.     mov    ax,wParm1
  216.     mov    [DMAUnitSize],ax    ; max size of each DMA division
  217. ;
  218. ; flush any prior low-level setup
  219. ;
  220.     call    InitPCM
  221.     mov    DMARunning,0        ; signal it dead
  222. ;
  223. ; all done, return home
  224. ;
  225.     pop    es
  226.     pop    bp
  227.     ret
  228.  
  229. BackgroundInit    endp
  230.  
  231. endif   ; COMMDATA
  232. if BLOCKOUT
  233.  
  234. ;   /*\
  235. ;---|*|------------====< _dofread ( char far *, int, int ) >====------------
  236. ;---|*|
  237. ;---|*| Replacement code for the fread C library function. This will also
  238. ;---|*| keep track of the file position.
  239. ;---|*|
  240. ;---|*| Entry Conditions:
  241. ;---|*|     char far * is a pointer to the buffer
  242. ;---|*|     int - Length of the buffer
  243. ;---|*|     int - file handle
  244. ;---|*|
  245. ;---|*| Exit Conditions:
  246. ;---|*|     AX holds the length read from disk
  247. ;---|*|
  248. ;   \*/
  249.  
  250.     public    _dofread
  251. _dofread    proc
  252.     push    bp
  253.     mov    bp,sp
  254.     push    ds
  255.  
  256.         lds     dx,wParm1               ; get the buffer
  257.     mov    cx,wParm3        ; get the length
  258.     mov    bx,wParm4        ; get the handle
  259.     mov    ah,3fh            ; read command
  260.  
  261.     int    21h
  262.  
  263.     pop    ds
  264.  
  265.         cmc                             ; set carry if good read
  266.     sbb    bx,bx
  267.     and    ax,bx
  268.     add    wptr [__fptrpos+0],ax
  269.     adc    wptr [__fptrpos+2],0
  270.  
  271.     pop    bp
  272.     ret
  273.  
  274. _dofread    endp
  275.  
  276.  
  277. ;   /*\
  278. ;---|*|--------------====< FlushBuffer >====-----------------
  279. ;---|*|
  280. ;---|*| Flush the buffer by filling it with silence (value of 0x80)
  281. ;---|*|
  282. ;---|*| Entry Conditions:
  283. ;---|*|       dParm1 is the far pointer to the block
  284. ;---|*|       wParm2 is an unsigned integer which is the block length
  285. ;---|*|
  286. ;---|*| Exit Conditions:
  287. ;---|*|       DX:AX hold the ending pointer
  288. ;---|*|
  289. ;---|*| Prototype:
  290. ;---|*|
  291. ;---|*| char far * FlushBuffer (char far *, int)
  292. ;---|*|
  293. ;---|*|
  294. ;   \*/
  295.  
  296.         public  FlushBuffer
  297. FlushBuffer    proc
  298.     push    bp
  299.     mov    bp,sp
  300.  
  301.     push    es
  302.     push    di
  303.  
  304.     pushf
  305.     cld
  306.  
  307.     les    di,dParm1        ; grab 2 words off the stack
  308.     mov    cx,wParm3        ; wParm3 is used to skip the 2nd word
  309.  
  310.     cmp    [__pcmdatasize],9    ; 8 bit sets the carry
  311.     sbb    al,al            ; al = ff if 8 bit PCM
  312.     and    al,80h            ; al = 80 if 8 bit, 00 if 16 bit
  313.  
  314.     jcxz    @F
  315.     rep    stosb
  316.     @@:
  317.  
  318.     mov    dx,es            ; return the ending ptr
  319.     mov    ax,di
  320.  
  321.         popf
  322.  
  323.     pop    di
  324.     pop    es
  325.     pop    bp
  326.     ret
  327.  
  328. FlushBuffer    endp
  329.  
  330. endif   ; BLOCKOUT
  331. if BLOCKIN
  332.  
  333. ;   /*\
  334. ;---|*|------------====< _dofwrite ( char far *, int, int ) >====------------
  335. ;---|*|
  336. ;---|*| Replacement code for the fwrite C library function. This will also
  337. ;---|*| keep track of the file position.
  338. ;---|*|
  339. ;---|*| Entry Conditions:
  340. ;---|*|     char far * is a pointer to the buffer
  341. ;---|*|     int - Length of the buffer
  342. ;---|*|     int - file handle
  343. ;---|*|
  344. ;---|*| Exit Conditions:
  345. ;---|*|     AX holds the length writtent to disk
  346. ;---|*|
  347. ;   \*/
  348.     public    _dofwrite
  349. _dofwrite    proc
  350.     push    bp
  351.     mov    bp,sp
  352.     push    ds
  353.  
  354.         lds     dx,wParm1               ; get the buffer
  355.     mov    cx,wParm3        ; get the length
  356.     mov    bx,wParm4        ; get the handle
  357.     mov    ah,40h            ; write command
  358.  
  359.     int    21h
  360.  
  361.         pop     ds
  362.  
  363.     cmc                ; set carry if good read
  364.     sbb    bx,bx
  365.     and    ax,bx
  366.     add    wptr [__fptrpos+0],ax
  367.     adc    wptr [__fptrpos+2],0
  368.  
  369.     pop    bp
  370.     ret
  371.  
  372. _dofwrite    endp
  373.  
  374.  
  375. ;   /*\
  376. ;---|*|------------====< StartTheDMAInput() >====------------
  377. ;---|*|
  378. ;---|*| Calculate the H/W timer value (internal routine)
  379. ;---|*|
  380. ;---|*| Entry Conditions:
  381. ;---|*|       pointer to a routine
  382. ;---|*|
  383. ;---|*| Exit Conditions:
  384. ;---|*|       AX =  0 indicates DMA running
  385. ;---|*|       AX = -1 indicates a failure
  386. ;---|*|
  387. ;---|*| Functionality:
  388. ;---|*|
  389. ;---|*|     Reset input pointer to the DMA buffer.
  390. ;---|*|     Load next buffer of data into the DMA buffer.
  391. ;---|*|     Enable DMA & interrupts.
  392. ;---|*|     Set DMARunning to 1;
  393. ;---|*|
  394. ;   \*/
  395.  
  396.     public StartTheDMAInput
  397. StartTheDMAInput        proc
  398.     push    bp
  399.     mov    bp,sp
  400.  
  401.         push    es
  402. ;
  403. ; Reset the DMA's internal buffer pointer & counter
  404. ;
  405.     call    _resetdmaptrs        ; reset the criticals
  406. ;
  407. ; Validate some critical data
  408. ;
  409.     mov    ax,-1            ; setup for bad return
  410.  
  411.     cmp    DMAUnitSize,0        ; we must have a valid size of units
  412.     jz    stdmaout_bad
  413.  
  414.     les    bx,[NextDMAPtr]     ; we must have a valid DMA buffer
  415.     mov    cx,es
  416.     or    bx,cx
  417.         jz      stdmaout_bad
  418. ;
  419. ; setup the callers callback
  420. ;
  421.       if @codesize
  422.     mov    ax,wParm1+0
  423.     mov    dx,wParm1+2
  424.     mov    wptr [__callersroutine+0],ax
  425.     mov    wptr [__callersroutine+2],dx
  426.       else
  427.         mov     ax,wParm1+0
  428.     mov    [__callersroutine],ax
  429.       endif
  430. ;
  431. ; setup our call-back routine
  432. ;
  433.     lea    ax,InputBackgroundTask
  434.     push    cs
  435.     push    ax
  436.     call    UserFunc
  437.     add    sp,4
  438. ;
  439. ; The DMA is loaded, let'er rip!!!
  440. ;
  441.     call    PCMRecord
  442.     mov    DMARunning,1
  443.  
  444.     sub    ax,ax
  445. ;
  446. stdmaout_bad:
  447.     pop    es
  448.     pop    bp
  449.     ret
  450.  
  451. StartTheDMAInput    endp
  452.  
  453. endif    ; BLOCKIN
  454. if BLOCKOUT
  455.  
  456. ;   /*\
  457. ;---|*|------------====< StartTheDMAOutput() >====------------
  458. ;---|*|
  459. ;---|*| Calculate the H/W timer value (internal routine)
  460. ;---|*|
  461. ;---|*| Entry Conditions:
  462. ;---|*|       None
  463. ;---|*|
  464. ;---|*| Exit Conditions:
  465. ;---|*|       AX =  0 indicates DMA running
  466. ;---|*|       AX = -1 indicates a failure
  467. ;---|*|
  468. ;---|*| Functionality:
  469. ;---|*|
  470. ;---|*|     Reset input pointer to the DMA buffer.
  471. ;---|*|     Load next buffer of data into the DMA buffer.
  472. ;---|*|     Enable DMA & interrupts.
  473. ;---|*|     Set DMARunning to 1;
  474. ;---|*|
  475. ;   \*/
  476.  
  477.     public    StartTheDMAOutput
  478. StartTheDMAOutput       proc
  479.         push    bp
  480.         mov     bp,sp
  481.     push    es
  482. ;
  483. ; Reset the DMA's internal buffer pointer & counter
  484. ;
  485.         call    _resetdmaptrs           ; reset the criticals
  486. ;
  487. ; Validate some critical data
  488. ;
  489.     mov    ax,-1            ; setup for bad return
  490.  
  491.     cmp    DMAUnitSize,0        ; we must have a valid size of units
  492.     jz    stdmaout_bad
  493.  
  494.     les    bx,[NextDMAPtr]     ; we must have a valid DMA buffer
  495.     mov    cx,es
  496.     or    bx,cx
  497.         jz      stdmaout_bad
  498. ;
  499. ; setup the callers callback
  500. ;
  501.       if @codesize
  502.     mov    ax,wParm1+0
  503.     mov    dx,wParm1+2
  504.     mov    wptr [__callersroutine+0],ax
  505.     mov    wptr [__callersroutine+2],dx
  506.       else
  507.         mov     ax,wParm1+0
  508.     mov    [__callersroutine],ax
  509.       endif
  510. ;
  511. ; setup our call-back routine
  512. ;
  513.     lea    ax,OutputBackgroundTask
  514.     push    cs
  515.     push    ax
  516.     call    UserFunc
  517.     add    sp,4
  518. ;
  519. ; The DMA is loaded, let'er rip!!!
  520. ;
  521.     call    PCMPlay
  522.     mov    DMARunning,1
  523.  
  524.     sub    ax,ax
  525. ;
  526. stdmaout_bad:
  527.     pop    es
  528.         pop     bp
  529.     ret
  530.  
  531. StartTheDMAOutput    endp
  532.  
  533. endif ;; BLOCKOUT
  534.  
  535. ;
  536. ;--------------------------=============================-----------------------
  537. ;--------------------------====< Internal Routines >====-----------------------
  538. ;--------------------------=============================-----------------------
  539. ;
  540.  
  541. if BLOCKIN
  542. ;   /*\
  543. ;---|*|------------====< InputBackgroundTask() >====------------
  544. ;---|*|
  545. ;---|*| This is the interrupt code for processing DMA-buffer-has-data interrupts
  546. ;---|*|
  547. ;---|*| Entry Conditions:
  548. ;---|*|     None
  549. ;---|*|
  550. ;---|*| Exit Conditions:
  551. ;---|*|     None
  552. ;---|*|
  553. ;---|*| Interrupt handling:
  554. ;---|*|
  555. ;---|*|     if Next Buffer has data,
  556. ;---|*|     Kill-the-DMA;
  557. ;---|*|     set DMARunning to 0;
  558. ;---|*|     exit interrupt.
  559. ;---|*|     else
  560. ;---|*|        Load DMA into Next buffer.
  561. ;---|*|
  562. ;---|*|     Increment BufferDataCount.
  563. ;---|*|     Increment ProcessBlockCount.
  564. ;---|*|
  565. ;   \*/
  566.  
  567. InputBackgroundTask    proc
  568.     push    ax            ; save the entire state
  569.     push    bx
  570.     push    cx
  571.     push    dx
  572.     push    si
  573.     push    di
  574.     push    ds
  575.     push    es
  576. ;
  577. ; initialize the segment registers to point to our local static segment
  578. ;
  579. if MODELSIZE eq 0
  580.     mov    ax,cs            ; load our data segment
  581.         mov     ds,ax                   ; DS too in case of failure
  582. else
  583.         mov     ax,@data                ; load our data segment
  584.     mov    ds,ax            ; DS too in case of failure
  585. endif
  586.  
  587. ;
  588. ; Save the next DMA pointer, increment our internal buffer-loaded count
  589. ;
  590.         inc     ProcessedBlockCount     ; total block count the DMA has seen
  591.         inc     BufferDataCount         ; tell the world, we have new data
  592.     mov    ax,BufferDataCount
  593.     cmp    ax,MaxBuffCount
  594.     jb    inbkgrtsk_exit
  595. ;
  596. ; Yuck! We just ran out of buffer space, we must kill the DMA
  597. ;
  598.         call    StopPCM                 ; kill the interrupts...
  599.     mov    DMARunning,0
  600. ;
  601. inbkgrtsk_exit:
  602.   if @codesize
  603.     cmp    wptr [__callersroutine+2],0  ; if there is no vector, just exit
  604.     jz    @F
  605.     call    dptr [__callersroutine]      ; call the user routine
  606.       @@:
  607.   else
  608.     cmp    wptr [__callersroutine],0    ; if there is no vector, just exit
  609.     jz    @F
  610.     call    wptr [__callersroutine]      ; call the user routine
  611.       @@:
  612.   endif
  613. ;
  614. ; Call the application level it it wants a slice of time...
  615. ;
  616.         cmp     wptr [__synccallback+2],0    ; if no App. vector, just exit
  617.     jz    @F
  618.     call    dptr [__synccallback]         ; if no App. vector, just exit
  619.     @@:
  620. ;
  621. ; finally, all done.
  622. ;
  623.         pop     es
  624.     pop    ds
  625.     pop    di
  626.     pop    si
  627.     pop    dx
  628.     pop    cx
  629.     pop    bx
  630.     pop    ax
  631.     retf
  632.  
  633. InputBackgroundTask    endp
  634. endif    ; BLOCKIN
  635.  
  636.  
  637. if BLOCKOUT
  638. ;   /*\
  639. ;---|*|------------====< OutputBackgroundTask() >====------------
  640. ;---|*|
  641. ;---|*| This is the interrupt code for processing DMA buffer
  642. ;---|*| empty interrupts for the file output routines.
  643. ;---|*|
  644. ;---|*| Entry Conditions:
  645. ;---|*|     None
  646. ;---|*|
  647. ;---|*| Exit Conditions:
  648. ;---|*|     None
  649. ;---|*|
  650. ;---|*| Interrupt handling:
  651. ;---|*|
  652. ;---|*|     If BufferDataCount       is zero,
  653. ;---|*|     Kill-the-DMA;
  654. ;---|*|     set DMARunning to 0;
  655. ;---|*|
  656. ;---|*|     Attempt to load as many blocks as possible into the DMA buffer.
  657. ;---|*|
  658. ;---|*|     If data is loaded and DMARunning = 0,
  659. ;---|*|     restart the DMA;
  660. ;---|*|     set DMARunning to -1;
  661. ;---|*|
  662. ;---|*|     Exit interrupt.
  663. ;---|*|
  664. ;   \*/
  665.  
  666. OutputBackgroundTask    proc
  667.     push    ax            ; save the entire state
  668.     push    bx
  669.     push    cx
  670.     push    dx
  671.     push    si
  672.     push    di
  673.     push    ds
  674.     push    es
  675. ;
  676. ; initialize the data segment to point to our local static segment
  677. ;
  678. if MODELSIZE eq 0
  679.     mov    ax,cs            ; load our data segment
  680.         mov     ds,ax                   ; DS too in case of failure
  681. else
  682.         mov     ax,@data                ; load our data segment
  683.     mov    ds,ax
  684. endif
  685. ;
  686. ; We just finished a block. If done (0), stop the DMA, else go load another
  687. ;
  688.     inc    ProcessedBlockCount    ; total block count the DMA has seen
  689.         sub     BufferDataCount,1       ; decrement the internal buffered data
  690.     adc    BufferDataCount,0    ; count down to zero
  691.     jnz    bkgrtsk_05        ; more data, go load it...
  692. ;
  693. ; Yuck! We just ran out of data, we must silence the DMA
  694. ;
  695.     call    StopPCM         ; kill the interrupts...
  696.     mov    DMARunning,0
  697. ;
  698. bkgrtsk_05:
  699.   if @codesize
  700.     cmp    wptr [__callersroutine+2],0  ; if there is no vector, just exit
  701.     jz    @F
  702.     call    dptr [__callersroutine]      ; call the user routine
  703.       @@:
  704.   else
  705.     cmp    wptr [__callersroutine],0    ; if there is no vector, just exit
  706.     jz    @F
  707.         call    wptr [__callersroutine]      ; call the user routine
  708.       @@:
  709.   endif
  710. ;
  711. ; Call the application level it it wants a slice of time...
  712. ;
  713.         cmp     wptr [__synccallback+2],0    ; if no App. vector, just exit
  714.     jz    @F
  715.     call    dptr [__synccallback]         ; if no App. vector, just exit
  716.     @@:
  717. ;
  718. ; finally, all done.
  719. ;
  720.         pop     es
  721.     pop    ds
  722.     pop    di
  723.     pop    si
  724.     pop    dx
  725.     pop    cx
  726.     pop    bx
  727.     pop    ax
  728.     retf
  729.  
  730. OutputBackgroundTask    endp
  731. endif    ; BLOCKOUT
  732.  
  733. if COMMDATA
  734. ;
  735. ;   /*\
  736. ;---|*|------------====< _resetdmaptrs >====----------------
  737. ;---|*|
  738. ;---|*| Reset the DMA starting point
  739. ;---|*|
  740. ;---|*| Entry Conditions:
  741. ;---|*|     DS points to the default data segment
  742. ;---|*|
  743. ;---|*| Exit Conditions:
  744. ;---|*|     None
  745. ;---|*|
  746. ;   \*/
  747.  
  748. _resetdmaptrs    proc
  749.     push    es
  750. ;
  751. ; load the number of buffer divisions. this tells us when to wrap the DMA buff
  752. ;
  753.     mov    al,byte ptr [MaxBuffCount]
  754.     mov    [CountdownBuffers],al
  755. ;
  756. ; reset the DMA buffer offset
  757. ;
  758.     les    ax,[StartOfDMABuffer]
  759.     mov    wptr [NextDMAPtr+0],ax
  760.     mov    wptr [NextDMAPtr+2],es
  761.  
  762.         pop     es
  763.     ret
  764.  
  765. _resetdmaptrs   endp
  766.  
  767. endif    ; COMMDATA
  768.  
  769. ;   /*\
  770. ;---|*| end of PCMIOA.ASM
  771. ;   \*/
  772.  
  773.         end
  774.  
  775.